package com.example.demo.service;

import com.example.demo.client.KookWebSocketClient;
import com.example.demo.config.KookProperties;
import com.example.demo.handler.MessageHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PreDestroy;
import java.net.URI;

@Slf4j
@Service
public class KookBotService implements KookWebSocketClient.ReconnectAware {



    private final KookProperties kookProperties;
    private final ObjectMapper objectMapper;
    private final RestTemplate restTemplate;
    private final MessageHandler messageHandler;
    private KookWebSocketClient webSocketClient;
    private static final String GATEWAY_URL = "https://www.kookapp.cn/api/v3/gateway/index";

    @Autowired
    public KookBotService(KookProperties kookProperties, ObjectMapper objectMapper, MessageHandler messageHandler) {
        this.kookProperties = kookProperties;
        this.objectMapper = objectMapper;
        this.messageHandler = messageHandler;
        this.restTemplate = new RestTemplate();
    }

    @EventListener(ApplicationReadyEvent.class)
    public void start() {
        connectWebSocket();
    }

    @Override
    public void onReconnectRequired() {
        log.info("收到重连请求，准备重新连接");
        scheduleReconnect();
    }

    private void connectWebSocket() {
        try {
            String gatewayUrl = getGatewayUrl();
            if (gatewayUrl == null) {
                log.error("无法获取Gateway URL");
                return;
            }
            log.info("gatewayUrl={}", gatewayUrl);

            // 构建WebSocket URL
            String wsUrl = gatewayUrl;
            
            // 如果是重连，添加resume参数
            if (webSocketClient != null && webSocketClient.getSessionId() != null) {
                wsUrl += "&resume=1&session_id=" + webSocketClient.getSessionId() + "&sn=" + webSocketClient.getSn();
            }

            // 关闭现有连接
            if (webSocketClient != null) {
                webSocketClient.close();
            }
            log.info("wsUrl={}", wsUrl);
            // 创建新的WebSocket客户端
            webSocketClient = new KookWebSocketClient(new URI(wsUrl), kookProperties, objectMapper, messageHandler, this);
            webSocketClient.connect();

        } catch (Exception e) {
            log.error("连接WebSocket时发生错误", e);
            // 添加重试逻辑
            scheduleReconnect();
        }
    }

    private String getGatewayUrl() {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", "Bot " + kookProperties.getToken());

            // 使用RestTemplate获取Gateway URL，添加请求头
            org.springframework.http.HttpEntity<?> entity = new org.springframework.http.HttpEntity<>(headers);
            String requestUrl = GATEWAY_URL + "?compress=" + kookProperties.getWebsocket().getCompress();
            org.springframework.http.ResponseEntity<String> response = restTemplate.exchange(
                requestUrl,
                org.springframework.http.HttpMethod.GET,
                entity,
                String.class
            );
            String responseBody = response.getBody();
            return objectMapper.readTree(responseBody).get("data").get("url").asText();
        } catch (Exception e) {
            log.error("获取Gateway URL时发生错误", e);
            return null;
        }
    }

    private int reconnectAttempts = 0;
    private static final int MAX_RECONNECT_DELAY = 60000; // 最大重连延迟（毫秒）
    private static final int INITIAL_RECONNECT_DELAY = 1000; // 初始重连延迟（毫秒）

    private void scheduleReconnect() {
        new Thread(() -> {
            try {
                // 计算指数退避延迟时间
                int delay = Math.min(
                    INITIAL_RECONNECT_DELAY * (1 << Math.min(reconnectAttempts, 6)), // 2的指数增长
                    MAX_RECONNECT_DELAY
                );
                
                log.info("计划在{}毫秒后进行第{}次重连尝试", delay, reconnectAttempts + 1);
                Thread.sleep(delay);
                
                reconnectAttempts++;
                connectWebSocket();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("重连等待被中断", e);
            }
        }).start();
    }

    @PreDestroy
    public void stop() {
        if (webSocketClient != null) {
            webSocketClient.close();
        }
    }
}